package com.itheima.tanhua.service;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.autoconfig.template.OssTemplate;
import com.itheima.tanhua.Dto.MovementDto;
import com.itheima.tanhua.api.db.UserInfoApi;
import com.itheima.tanhua.api.mongodb.CommentApi;
import com.itheima.tanhua.api.mongodb.TimeLineApi;
import com.itheima.tanhua.enums.CommentType;
import com.itheima.tanhua.enums.Constants;
import com.itheima.tanhua.pojo.db.UserInfo;
import com.itheima.tanhua.pojo.mongo.Comment;
import com.itheima.tanhua.pojo.mongo.Movement;
import com.itheima.tanhua.api.mongodb.MovementApi;
import com.itheima.tanhua.pojo.mongo.MovementTimeLine;
import com.itheima.tanhua.utils.RelativeDateFormat;
import com.itheima.tanhua.vo.MovementsVo;
import com.itheima.tanhua.vo.PageResult;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MovementService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private TimeLineService timeLine1Service;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private TimeLineApi timeLineApi;

    @DubboReference
    private CommentApi commentApi;
    /**
     * 取消点赞-1
     *
     * @param movementId 动态id
     * @return
     */
    public  Integer updateDisLike(String movementId) {
        return movementApi.updateDisLike(movementId);

    }

    //  好友动态和单个动态  都只有一个点赞

    /**
     * 添加动态 好友可查看
     *
     * @param movementDto
     * @param imageContent
     */
    public void saveMovements(MovementDto movementDto, MultipartFile[] imageContent) {
        /*
        1.添加动态数据
        2.记录到时间线中
        3.查询好友的列表
        4.记录到好友的关系表中
         */
        try {
            //1获取当前的用户
            String uid = stringRedisTemplate.opsForValue().get("CHECK_ID");
            //2添加动态 movement  中的数据
            //2.1  进行数据处理
            Movement movement = new Movement();
            BeanUtil.copyProperties(movementDto, movement);
            movement.setLocationName(movementDto.getLocation());
            movement.setCreated(System.currentTimeMillis());
            movement.setUserId(Convert.toLong(uid));

            List urls = new ArrayList();
            //传输文件到阿里云 获取地址
            for (MultipartFile multipartFile : imageContent) {
                String url = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
                urls.add(url);
            }
            movement.setMedias(urls);
            Movement mv = movementApi.saveMovements(movement);
            //进行一个异步添加
            timeLine1Service.saveTimeLine(Convert.toLong(uid), mv.getId());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    ////是分离出来的结果集
    private MovementsVo getMovementsVo(Movement movement, UserInfo userInfo) {

        MovementsVo movementsVo = new MovementsVo();
        BeanUtil.copyProperties(userInfo, movementsVo, "id");
        movementsVo.setTags(userInfo.getTags().split(","));

        BeanUtil.copyProperties(movement, movementsVo, "id");
        movementsVo.setImageContent(movement.getMedias().toArray(new String[0]));
        movementsVo.setId(movement.getId().toHexString());
        movementsVo.setDistance("500米");
        movementsVo.setCreateDate(RelativeDateFormat.format(new Date(movement.getCreated())));

//        movementsVo.setLikeCount(0);
//        movementsVo.setLoveCount(0);
//        movementsVo.setCommentCount(0);
        return movementsVo;
    }

    //结果集二    在好友和当动态中  只有点赞一个
    private void likeShow(Long uid, Movement movement, MovementsVo movementsVo) {
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + uid;
        //将是否点赞保存到redis中 使用hash表
        /*if (stringRedisTemplate.opsForHash().hasKey(redisKey, hashKey)){
            movementsVo.setHasLiked(1);
        }*/
        Object i = stringRedisTemplate.opsForHash().get(redisKey, hashKey);
        movementsVo.setHasLiked(ObjectUtil.equal(i,1)?1:0);

    }

    //结果集三    推荐和我的动态中  有点赞和喜欢
    private void likeAndLoveShow(Long uid, Movement movement, MovementsVo movementsVo) {
        likeShow(uid, movement, movementsVo);
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + uid;
        //将是否点赞保存到redis中 使用hash表
        Object i = stringRedisTemplate.opsForHash().get(redisKey, hashKey);
        movementsVo.setHasLoved(ObjectUtil.equal(i,1)?1:0);
    }


    /**
     * 查看个人动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findMovementAll(Long userId, Integer page, Integer pagesize) {
        /**
         * 查看个人动态    数据库 从通过动态的集合查询所有的动态
         *  通过uid去获取用户的详细信息
         *  结果集会存取movementsVo的
         */
        //获取redis中存取的uid
//        String uid = stringRedisTemplate.opsForValue().get("CHECK_ID");
        //通过uid 获取所有的动态集合
        List<Movement> movementList = movementApi.findMovementAll(userId, page, pagesize);
        //都是用户本身发送 Mysql
        UserInfo userInfo = userInfoApi.selectById(userId);
        List<MovementsVo> Vos = new ArrayList<>();
        //将数据填充到vo中
        int counts = 0;
        for (Movement movement : movementList) {
            counts++;
            MovementsVo movementsVo = getMovementsVo(movement, userInfo);
            //调用喜欢和点赞的标注方法
            likeAndLoveShow(userId, movement, movementsVo);
            Vos.add(movementsVo);
        }
        PageResult pageResult = new PageResult(page, pagesize, Vos, counts/pagesize, counts);
        return pageResult;
    }
    /**
     * 查询好友的动态信息
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findFriendMovement(Integer page, Integer pagesize) {
        /**
         * 好友的动态是通过好友的id去获取
         * 1.是friend集合 通过uid查询到好友的friendId 再去查询时间线 获取动态的id   查询动态 三张表
         * 2.是转换位置  直接查询时间线以我作为friendId查询与我相交的朋友发送动态的id   查询动态  两张表
         */
        //1.获取uid的值
        Long uid = Convert.toLong(stringRedisTemplate.opsForValue().get("CHECK_ID"));
        //2.时间线集合  转换角色 查询动态的id   是个集合
        List<MovementTimeLine> movementTimeLines = timeLineApi.findTimeLine(uid);

        List<Object> ids = CollUtil.getFieldValues(movementTimeLines, "movementId");

        //3.通过动态的id  查询动态的数据
        List<Movement> movementList = movementApi.findMovementById(ids, page, pagesize);
        //4.封装数据
        List<MovementsVo> Vos = new ArrayList<>();
        int counts = 0;
        for (Movement movement : movementList) {
            counts++;
            UserInfo userInfo = userInfoApi.selectById(movement.getUserId());
            //查询朋友的详细信息
            MovementsVo movementsVo = getMovementsVo(movement, userInfo);
            likeShow(uid, movement, movementsVo);
            Vos.add(movementsVo);
        }
        PageResult pageResult = new PageResult(page, pagesize, Vos, counts/pagesize, counts);
        return pageResult;
    }


    /**
     * 用户推荐的动态 并且分页
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findMovements(Integer page, Integer pagesize) {
        /**
         * 推荐的动态查询  使用redis存取   找不到在随机的取出数据pids
         * 通过pid  查询到动态 获取动态的信息 找到发送信息人的详细信息
         * 封装到Vo中
         */
        //从redis中取出uid
        Long uid = Convert.toLong(stringRedisTemplate.opsForValue().get("CHECK_ID"));
        //从redis中取出存入的数据
        String redisKey = "MOVEMENTS_RECOMMEND_" + uid;
        String redisValue = stringRedisTemplate.opsForValue().get(redisKey);
        List<Movement> movementList = new ArrayList<>();
        if (StrUtil.isBlank(redisValue)) {
            //redis中没有pid的数据   需要随机的取出数据
            movementList = movementApi.randomMovements(pagesize);
        } else {
            //有值就直接通过pid去查询动态
            String[] values = redisValue.split(",");

            if ((page - 1) * pagesize < values.length) {
                //将字符串去进行分页并转换成Long的格式
                List<Long> pids = Arrays.stream(values)
                        .map(e -> Convert.toLong(e))
                        .skip((page - 1) * pagesize).limit(pagesize)
                        .collect(Collectors.toList());
                movementList = movementApi.findMovementByPid(pids);
            }
        }
        //list的值已经获取
        List<MovementsVo> Vos = new ArrayList<>();
        int counts = 0;
        for (Movement movement : movementList) {
            counts++;
            UserInfo userInfo = userInfoApi.selectById(movement.getUserId());
            //查询朋友的详细信息
            MovementsVo movementsVo = getMovementsVo(movement, userInfo);
            likeAndLoveShow(uid, movement, movementsVo);
            Vos.add(movementsVo);
            //判断点赞
            String s = stringRedisTemplate.opsForValue().get("CHECK_ID");
            s = stringRedisTemplate.opsForValue().get(s + movement.getId());
            if (!ObjectUtil.isEmpty(s)){
                movementsVo.setHasLiked(1);
            }
            //判断喜欢key是uid+movementId+"love"
            String love = stringRedisTemplate.opsForValue().get("CHECK_ID");
             love = stringRedisTemplate.opsForValue().get(love + movement.getId()+"love");
            if (!ObjectUtil.isEmpty(love)){
                movementsVo.setHasLoved(1);
            }

        }
        PageResult pageResult = new PageResult(page, pagesize, Vos, counts/pagesize, counts);
        return pageResult;

    }


    /**
     * 根据movementId查询单条数据信息
     *
     * @param movementId
     * @return
     */
    public MovementsVo findOneById(String movementId) {

        Long uid = Convert.toLong(stringRedisTemplate.opsForValue().get("CHECK_ID"));
        //通过movementId 查询出movement的对象
        Movement movement = movementApi.findOneByMoventId(movementId);
        //进行补全数据
        UserInfo userInfo = userInfoApi.selectById(movement.getUserId());

        // TODO  保存访客记录信息

        MovementsVo movementsVo = getMovementsVo(movement, userInfo);
        likeShow(uid, movement, movementsVo);
        return movementsVo;
    }
    /**
     * 动态点赞+1
     *
     * @param movementId 动态id
     * @return
     */
    public Integer updateLikeCount(String movementId) {
        Integer count = movementApi.updateLikeCount(movementId);
        return count;
    }

    public Integer updateLoveCount(String movementId) {
        return movementApi.updateLoveCount(movementId);
    }

    public Integer updateDisLove(String movementId) {
        return movementApi.updateDis(movementId);
    }
}
